<?php


namespace App\Http\Controllers\Api;
use App\Http\Controllers\BaseController;
use App\Models\Address;
use App\Models\AddressSnapshot;
use App\Models\Cart;
use App\Models\MallFullReduction;
use App\Models\MallOrder;
use App\Models\MallOrderProduct;
use App\Models\MallOrderProductSnapshot;
use App\Models\MallProductStock;
use App\Models\MallRefund;
use App\Models\Product;
use App\Models\User;
use App\Services\MallOrderService;
use App\Services\MallRefundService;
use App\Services\ZeroJoinCheckService;
use Illuminate\Http\Request;
use function EasyWeChat\Kernel\Support\get_client_ip;

class MallOrderController extends BaseController
{

    public function index(Request $request) {
        $status = $request->input('status', -1);
        $comment_status = $request->input('comment_status', 0);
        if ($comment_status) {
            $status = MallOrder::STATUS_FINISH;
        }
        $list = MallOrder::where('user_id', $this->getUserId())->status($status)
            ->when($comment_status, function ($q) use($comment_status) {
                $q->where('comment_status', $comment_status);
            })
            ->withCertain('order_product.product', ['title', 'image_url'])
            ->withCertain('order_product_zero.product', ['title', 'image_url'])
            ->orderBy('id', 'desc')
            ->paginate(\request('per_page', 20));

        return $this->paginate($list);
    }

    public function info(Request $request)
    {
        $id = $request->input('id');
        $info = MallOrder::withCertain('address', ['contact', 'phone', 'province', 'city', 'area', 'detail'])
            ->with(['order_product_zero' => function($q){
                $q->select(['id','product_snapshot_id', 'order_id']);
            }, 'order_product_zero.product' => function($q) {
                $q->select(['id','title', 'image_url']);
            }])
            ->withCertain('order_product.product', ['title', 'is_specs', 'image_url'])->find($id);
        if (!$info)
            return $this->failed('订单不存在');
        $user_id = $this->getUserId();
        if ($info->user_id != $user_id)
            return $this->failed('无权查看别人订单号');

        if ($info->status == MallOrder::STATUS_WAIT_PAY) {
            $diff_time = strtotime($info->created_at) + 3*24* 3600 - time();
            if ($diff_time <= 0) {
                $input = [
                    'order_id' => $id,
                    'close_type' => MallOrder::CLOSE_TYPE_SYSTEM
                ];
                MallOrderService::handle($input, 'cancel');

                $info = MallOrder::withCertain('address', ['contact', 'phone', 'province', 'city', 'area', 'detail'])
                    ->withCertain('order_product.product', ['title', 'is_specs', 'image_url'])->find($id);

            } else {
                $info->left_time = $diff_time > 0 ? time2string($diff_time) : 0;
            }
        } else if ($info->status == MallOrder::STATUS_DELIVER_PRODUCT) {
            //是否存在正在退货中
            $exist_other_refunding = MallOrderProduct::where('order_id', $info->id)
                ->whereIn('refund_status', [1, 2, 3])->exists();
            if (!$exist_other_refunding) {
                $diff_time = strtotime($info->express_end_at) - time();
                if ($diff_time <= 0) {
                    $input = [
                        'order_id' => $id
                    ];
                    MallOrderService::handle($input, 'receive');

                    $info = MallOrder::withCertain('address', ['contact', 'phone', 'province', 'city', 'area', 'detail'])
                        ->withCertain('order_product.product', ['title', 'is_specs', 'image_url'])->find($id);
                } else {
                    $info->left_time = $diff_time > 0 ? time2string($diff_time) : 0;
                }
            } else {
                $info->left_time = '10天0小时0分';
            }
        }

        return $this->success($info);
    }

    public function order_product_info(Request $request) {
        $this->validate($request, [
            'order_product_id' => 'required',
        ]);
        $input = $request->input();
        try {
            $input['user_id'] = $this->getUserId();
            $order_product = MallOrderProduct::withCertain('product', ['title', 'image_url'])->find($input['order_product_id']);
            if (!$order_product)
                return $this->failed('商品不存在');
            return $this->success($order_product);
        } catch (\Exception $e) {
            \Log::error($e);
            return $this->failed($e->getMessage());
        }
    }


    public function destroy(Request $request) {
        $this->validate($request, [
            'ids' => 'required'
        ]);
        $ids = $request->input('ids');
        $arr_id = explode(",", $ids);
        $user_id = $this->getUserId();
        foreach ($arr_id as $id) {
            $info = MallOrder::find($id);
            if (!$info)
                return $this->failed('订单号不存在');
            if ($info->user_id != $user_id)
                return $this->failed('无权删除别人订单号');
            if (!in_array($info->status, [3, 4])) {
                return $this->failed('订单未完成不循序删除');
            }
            $info->delete();
        }
        return $this->success([]);
    }

    public function apply_refund(Request $request) {
        $this->validate($request, [
            'order_product_id' => 'required',
        ]);
        $input = $request->input();
        try {
            $input['user_id'] = $this->getUserId();
            $order_product = MallOrderProduct::find($input['order_product_id']);
            if (!$order_product)
                return $this->failed('商品不存在');
            $input['order_id'] = $order_product->order_id;
            MallOrderService::handle($input, 'refund');
            return $this->success([], '申请退款成功');
        } catch (\Exception $e) {
            return $this->failed($e->getMessage());
        }
    }

    public function refund_supply_express(Request $request) {
        $this->validate($request, [
            'refund_id' => 'required',
            'express_order_sn' => 'required',
        ]);
        $input = $request->input();
        $input['order_product_id'] = $input['refund_id'];
        unset($input['refund_id']);
        $refund = MallRefund::where('order_product_id', $input['order_product_id'])->first();
        if (!$refund)
            return $this->failed('退款单号不存在');
        if ($refund->status != MallRefund::STATUS_DELIVER_PRODUCT) {
            return $this->failed('退款中状态才允许填写物流单号');
        }
        $refund->express_order_sn = $input['express_order_sn'];
        $refund->save();
        return $this->success([], '提交成功');
    }

    public function refund_info(Request $request) {
        $this->validate($request, [
            'order_product_id' => 'required',
        ]);
        $input = $request->input();
        $refund = MallRefund::withCertain('order_product.product', ['title','video_url','image_url'])->where('order_product_id', $input['order_product_id'])->first();
        if (!$refund)
            return $this->failed('退款单号不存在');

        return $this->success($refund);
    }

    public function cancel_refund(Request $request) {
        $this->validate($request, [
            'refund_id' => 'required', //这里是order_product_id
        ]);
        $input = $request->input();
        $input['order_product_id'] = $input['refund_id'];
        unset($input['refund_id']);
        try {
            $input['user_id'] = $this->getUserId();
            $refund = MallRefund::where('order_product_id', $input['order_product_id'])->first();
            if (!$refund)
                return $this->failed('退款单号不存在');

            $input['refund_id'] = $refund->id;
            $input['order_product_id'] = $refund->order_product_id;
            MallRefundService::handle($input, 'cancel');
            return $this->success([], '取消成功');
        } catch (\Exception $e) {
            \Log::error($e);
            return $this->failed($e->getMessage());
        }
    }


    public function cancel(Request $request) {
        $this->validate($request, [
            'order_id' => 'required',
        ]);
        $input = $request->input();
        try {
            $input['close_type'] = MallOrder::CLOSE_TYPE_USER;
            MallOrderService::handle($input, 'cancel');
            return $this->success([], '取消成功');
        } catch (\Exception $e) {
            return $this->failed($e->getMessage());
        }
    }

    public function takeDeliver(Request $request) {
        $this->validate($request, [
            'order_id' => 'required',
        ]);
        $input = $request->input();
        try {
            MallOrderService::handle($input, 'receive');
            return $this->success([], '操作成功');
        } catch (\Exception $e) {
            return $this->failed($e->getMessage());
        }
    }

    public function createPay(Request $request) {
        $this->validate($request, [
            'order_id' => 'required',
        ]);
        $input = $request->input();
        $order = MallOrder::find($input['order_id']);
        if (!$order)
            return $this->failed('订单号不存在');

        if ($order->status != MallOrder::STATUS_WAIT_PAY)
            return $this->failed('订单号已关闭');

        $user = $this->getUser();
        if ($order->user_id != $user->id)
            return $this->failed('无权操作');
        try {
            return \DB::transaction(function () use($order, $user){
                $pay_order_sn = create_order_no('m');
                $order->pay_order_sn = $pay_order_sn;
                $order->save();
                MallOrderProduct::where('order_id', $order->id)->update(['pay_order_sn' => $pay_order_sn]);
                $response = $this->_ttPay($pay_order_sn, $order->paid_amount, $user);
                return $this->success(['order_id' => $order->id, 'pay' => $response]);
            });
        } catch (\Exception $e) {
            \Log::error($e);
            return $this->failed('创建支付失败');
        }
    }

    public function createOrder(Request $request) {
        $this->validate($request, [
            'cart_ids' => 'required',
            'address_id' => 'required',
        ]);
        $input = $request->input();
        $zero_product_id = $input['zero_product_id'] ?? 0;
        $zero_product = null;
        if ($zero_product_id) {
            $zero_product = Product::find($zero_product_id);
        }

        $input['pay_type'] = 0;
        $user = $this->getUser();
        $input = $request->input();
        if (isset($input['cart_ids'])) {
            $arr_cart_ids = explode(",", $input['cart_ids']);
        }
        if (empty($arr_cart_ids))
            return $this->failed('arr_ids参数空');

        $address = Address::find($input['address_id']);
        if (!$address)
            return $this->failed('地址不存在');

        $list = Cart::withCertain('product', ['is_full_reduction','title', 'fare', 'specs_detail_info', 'amount', 'vip_amount', 'is_specs', 'stock'])->when($arr_cart_ids, function ($q) use($arr_cart_ids){
            $q->whereIn('id', $arr_cart_ids);
        })->where('user_id', $this->getUserId())->orderBy('id', 'desc')
            ->paginate(\request('per_page', 100));

        if ($list->count() < 1)
            return $this->failed('购物车为空');

        //运费
        $group_list = $list->groupBy('producer_id')->toArray();

        try {
            \DB::beginTransaction();

            //地址快照
            $arr_address = $address->toArray();
            unset($arr_address['id'], $arr_address['address_display']);
            $address_snapshot = new AddressSnapshot();
            foreach ($arr_address as $key => $value) {
                $address_snapshot-> {$key} = $value;
            }
            $address_snapshot->save();

            //创建订单号
            $union_order_sn = create_order_no('m');

            $total_fee = 0;
            foreach ($group_list as $producer_id => $item) {
                $total_amount = 0;

                $arr_product = array_column($item, 'product');
                if (count($arr_product) != count(array_filter($arr_product))) {
                    throw new \Exception('购物车存在下架商品');
                }

                $order_sn = $union_order_sn . $producer_id;
                //判断是否满足满减包邮
                $is_satify_free_fare = false;

                foreach ($item as $val) {
                    $product = $val['product'];
                    $product_model = Product::find($val['product_id']);
                    if ($product['is_specs']) {
                        $match_val = $product['specs_detail_info'][$val['specs_str']];
                        $amount = $match_val['amount'] ?? '';
                        if (!$amount)
                            throw new \Exception($product['title'] . '商品规格不存在');
                        $vip_amount = $match_val['vip_amount'] ?? '';
                        $amount_yuan = !$user->is_vip ? $amount : $vip_amount;

                        $stock = MallProductStock::where('product_id', $val['product_id'])->where('key', $val['specs_str'])->value('stock') ?: 0;
                        if ($stock < $val['buy_num']) {
                            throw new \Exception($val['product']['title'] . ' - 库存不足');
                        }

                        //减规格库存
                        MallProductStock::where('product_id', $val['product_id'])->where('key', $val['specs_str'])->decrement('stock', $val['buy_num']);
                        MallProductStock::flushQueryCache();

                    } else {
                        $amount_yuan = format_yuan(!$user->is_vip ? $product['amount'] : $product['vip_amount']);

                        //判断当前商品剩余
//                        $sell_out_count = MallOrderProduct::where('product_id', $val['product_id'])->count();

                        if ( ( $val['buy_num']) > $product['stock'] ) {
                            throw new \Exception($val['product']['title'] . ' - 库存不足');
                        }


                    }
                    //减库存
                    $product_model->stock = $product_model->stock - $val['buy_num'];
                    $product_model->save();

                    $arr = $product_model->toArray();
                    unset($arr['amount_yuan'], $arr['vip_amount_yuan'], $arr['id'], $arr['fare_yuan']);
                    $snapshot = new MallOrderProductSnapshot();
                    foreach ($arr as $key => $value) {
                        if (in_array($key, ['video_url', 'image_url'])) {
                            $snapshot-> {$key} = json_encode_cn($value);
                        } else {
                            $snapshot-> {$key} = $value;
                        }
                    }
                    $snapshot->save();
                    $paid_amount = $amount_yuan * $val['buy_num'] * 100;
                    $total_amount += $paid_amount;
                    $sub = [
                        'order_sn' => $order_sn,
                        'pay_order_sn' => $union_order_sn,
                        'union_order_sn' => $union_order_sn,
                        'user_id' => $val['user_id'],
                        'producer_id' => $producer_id,
                        'product_id' => $val['product_id'],
                        'unit_amount' => $amount_yuan,
                        'paid_amount' => $paid_amount,
                        'buy_num' => $val['buy_num'],
                        'specs_str' => $val['specs_str'],
                        'specs_info' => $val['specs_info'],
                        'specs_info_show' => $val['specs_info_show'],
                        'product_snapshot_id' => $snapshot->id,
                        'address_snapshot_id' => $address_snapshot->id
                    ];
                    MallOrderProduct::create($sub);
                }


                //获取满减包邮
                $amount = MallFullReduction::where('merchant_id',$producer_id)->value('amount');
                if ($amount !== null) {
                    $amount = $amount * 100;
                    $is_satify_free_fare = ($amount - $total_amount) >0 ? false : true;
                }
                if (!$is_satify_free_fare) {
                    $fare = max(array_column($arr_product, 'fare')) * 100;
                    $total_amount += $fare;
                } else {
                    $fare = 0;
                    //判断是否同厂商
                    if ($zero_product && $zero_product->producer_id == $producer_id) {
                        //新增零元购
                        $ret = ZeroJoinCheckService::handle($user);
                        if ($ret['status'] == 1) {
                            $arr = $zero_product->toArray();
                            unset($arr['amount_yuan'], $arr['vip_amount_yuan'], $arr['id'], $arr['fare_yuan']);
                            $snapshot = new MallOrderProductSnapshot();
                            foreach ($arr as $key => $value) {
                                if (in_array($key, ['video_url', 'image_url'])) {
                                    $snapshot-> {$key} = json_encode_cn($value);
                                } else {
                                    $snapshot-> {$key} = $value;
                                }
                            }
                            $snapshot->save();
                            $sub = [
                                'order_sn' => $order_sn,
                                'pay_order_sn' => $union_order_sn,
                                'union_order_sn' => $union_order_sn,
                                'user_id' => $user->id,
                                'producer_id' => $producer_id,
                                'product_id' => $zero_product_id,
                                'unit_amount' => 0,
                                'paid_amount' => 0,
                                'buy_num' => 1,
                                'specs_str' => null,
                                'specs_info' => null,
                                'specs_info_show' => null,
                                'is_zero' => 1,
                                'product_snapshot_id' => $snapshot->id,
                                'address_snapshot_id' => $address_snapshot->id
                            ];
                            MallOrderProduct::create($sub);
                        }
                    }
                }
                $total_fee += $total_amount;
                $data = [
                    'order_sn' => $order_sn,
                    'user_id' => $this->getUserId(),
                    'producer_id' => $producer_id,
                    'pay_order_sn' => $union_order_sn,
                    'union_order_sn' => $union_order_sn,
                    'fare' => $fare,
                    'origin_amount' => $total_amount,
                    'paid_amount' =>  $total_amount,
                    'message' => $input['message'] ?? '',
                    'address_snapshot_id' => $address_snapshot->id,
                    'month' => date('Ym')
                ];
                $mall_order = MallOrder::create($data);
                MallOrderProduct::where('order_sn', $order_sn)->update(['order_id' => $mall_order->id]);
            }
            MallOrder::where('union_order_sn', $union_order_sn)->update(['union_total_amount' => $total_fee]);
            //删除购物车
            Cart::whereIn('id', $arr_cart_ids)->delete();


            $response = $this->_ttPay($union_order_sn, $total_fee, $user);
            \DB::commit();
            return $this->success(['order_id' => $mall_order->id, 'pay' => $response]);
        }catch (\Exception $e) {
            \DB::rollBack();
            \Log::error($e);
            return $this->failed($e->getMessage());
        }
    }

    private function _ttPay($union_order_sn, $total_fee, $user) {
        $total_amount = $total_fee / 100;
        $subject = '购买商品';
        //抖音支付
        if ($user->platform == User::PLATFORM_DY) {
            //生成支付配置
            $order = [
                'out_trade_no' => $union_order_sn,
                'total_amount' => $total_amount,
                'subject' => $subject,
            ];
            $ali_pay_url = $this->payApp()->app($order)->getContent();
            $config = [
                'out_trade_no' => $union_order_sn,
                'total_fee' => $total_fee,
                'body' => $subject,
                'spbill_create_ip' => get_client_ip(),
                'trade_type' => 'MWEB',
                'scene_info' => json_encode_cn([
                    'h5_info' => [
                        'type' => 'Wap',
                        'wap_url' => 'http://www.chuyouhui.top',
                        'wap_name' => $subject
                    ]
                ])
            ];
            $wx_pay_url = $this->payWx()->wap($config)->getTargetUrl();
            $app = $this->ttMini();
            $uid = $user->openid;
            $response = $app->payment->pay($uid, $union_order_sn, $total_fee, $subject, [
                'body' => $subject,
                'alipay_url' =>  $ali_pay_url,
                'wx_url' => $wx_pay_url,
                'valid_time' => '300',
                'notify_url' => 'http://www.chuyouhui.top',
                'risk_info' => ''
            ]);
        } else {
            $config = [
                'out_trade_no' => $union_order_sn,
                'total_fee' => $total_fee,
                'body' => $subject,
                'openid' => $user->openid,
                'trade_type' => 'JSAPI'
            ];
            $response = $this->payWx()->miniapp($config);
        }
        return $response;
    }


}

